diff --git a/kpimtextedit/tests/textedittest.cpp b/kpimtextedit/tests/textedittest.cpp index cdcf228f4..8eaf4c715 100644 --- a/kpimtextedit/tests/textedittest.cpp +++ b/kpimtextedit/tests/textedittest.cpp @@ -1,380 +1,427 @@ /* Copyright (c) 2009 Thomas McGuire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "qtest_kde.h" #include "textedittest.h" #include "../textedit.h" #include "kmime/kmime_codecs.h" #include #include #include #include using namespace KPIMTextEdit; QTEST_KDEMAIN( TextEditTester, GUI ) void TextEditTester::testFormattingUsed() { // This method tries to test everything that krichtextedit makes available, so // we can sure that in KMail, when the user uses some formatting, the mail is actually // sent as HTML mail TextEdit textEdit; QVERIFY( !textEdit.isFormattingUsed() ); // Insert some text. QTextCursor cursor( textEdit.document() ); cursor.insertText( QLatin1String( "Hello World!!" ) ); QVERIFY( !textEdit.isFormattingUsed() ); cursor.setPosition( 1 ); textEdit.setTextCursor( cursor ); // // Test link // QString someUrl = QLatin1String( "www.test.de" ); QString altText = QLatin1String( "Hello" ); textEdit.updateLink( someUrl, altText ); QVERIFY( textEdit.isFormattingUsed() ); QCOMPARE( textEdit.currentLinkUrl(), someUrl ); QCOMPARE( textEdit.currentLinkText(), altText ); cursor.setPosition( 1 ); textEdit.setTextCursor( cursor ); textEdit.updateLink( QString(), QLatin1String( "Hello" ) ); QVERIFY( textEdit.currentLinkUrl().isEmpty() ); QVERIFY( !textEdit.currentLinkText().isEmpty() ); QVERIFY( !textEdit.isFormattingUsed() ); // // Test alignment // cursor.setPosition( 1 ); textEdit.setTextCursor( cursor ); textEdit.alignRight(); QVERIFY( textEdit.isFormattingUsed() ); QCOMPARE( textEdit.alignment(), Qt::AlignRight ); textEdit.alignLeft(); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.alignCenter(); QCOMPARE( textEdit.alignment(), Qt::AlignHCenter ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.alignJustify(); QCOMPARE( textEdit.alignment(), Qt::AlignJustify ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.alignLeft(); QCOMPARE( textEdit.alignment(), Qt::AlignLeft ); QVERIFY( !textEdit.isFormattingUsed() ); // // Test lists // textEdit.setListStyle( QTextListFormat::ListCircle ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setListStyle( 0 ); QVERIFY( !textEdit.isFormattingUsed() ); // // Test font attributes // textEdit.setFontFamily( QLatin1String( "Times" ) ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setFontFamily( textEdit.document()->defaultFont().family() ); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.setFontSize( 48 ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setFontSize( textEdit.document()->defaultFont().pointSize() ); QVERIFY( !textEdit.isFormattingUsed() ); QFont myFont = textEdit.document()->defaultFont(); myFont.setStyle( QFont::StyleOblique ); textEdit.setFont( myFont ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setFont( textEdit.document()->defaultFont() ); QVERIFY( !textEdit.isFormattingUsed() ); // // Test bold, italic, underline and strikeout // textEdit.setTextBold( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextBold( false ); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.setTextUnderline( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextUnderline( false ); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.setTextItalic( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextItalic( false ); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.setTextStrikeOut( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextStrikeOut( false ); QVERIFY( !textEdit.isFormattingUsed() ); // // Color // QColor oldForeground = textEdit.document()->firstBlock().charFormat().foreground().color(); textEdit.setTextForegroundColor( Qt::red ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextForegroundColor( oldForeground ); QVERIFY( !textEdit.isFormattingUsed() ); QColor oldBackground = textEdit.document()->firstBlock().charFormat().background().color(); textEdit.setTextBackgroundColor( Qt::red ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextBackgroundColor( oldBackground ); QVERIFY( !textEdit.isFormattingUsed() ); // // Horizontal rule // textEdit.insertHorizontalRule(); QVERIFY( textEdit.isFormattingUsed() ); // No way to easily remove the horizontal line, so clear the text edit and start over textEdit.clear(); cursor.insertText( QLatin1String( "Hello World!!" ) ); QVERIFY( !textEdit.isFormattingUsed() ); cursor.setPosition( 1 ); textEdit.setTextCursor( cursor ); // // Sub and superscript // textEdit.setTextSuperScript( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextSuperScript( false ); QVERIFY( !textEdit.isFormattingUsed() ); textEdit.setTextSubScript( true ); QVERIFY( textEdit.isFormattingUsed() ); textEdit.setTextSubScript( false ); QVERIFY( !textEdit.isFormattingUsed() ); // // Image // QString imagePath = KIconLoader::global()->iconPath( QLatin1String( "folder-new" ), KIconLoader::Small, false ); textEdit.addImage( imagePath ); QVERIFY( textEdit.isFormattingUsed() ); cursor = textEdit.textCursor(); cursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, 1 ); cursor.removeSelectedText(); QVERIFY( !textEdit.isFormattingUsed() ); } void TextEditTester::testQuoting() { TextEdit edit; QVERIFY( edit.isLineQuoted( QLatin1String( "> Hello" ) ) ); QVERIFY( edit.isLineQuoted( QLatin1String( ">Hello" ) ) ); QVERIFY( !edit.isLineQuoted( QLatin1String( "Hello" ) ) ); QCOMPARE( edit.quoteLength( QLatin1String( "Hello" ) ), 0 ); QCOMPARE( edit.quoteLength( QLatin1String( ">Hello" ) ), 1 ); QCOMPARE( edit.quoteLength( QLatin1String( "> Hello" ) ), 2 ); QCOMPARE( edit.quoteLength( QLatin1String( ">>>Hello" ) ), 3 ); QCOMPARE( edit.quoteLength( QLatin1String( "> > > Hello" ) ), 6 ); QCOMPARE( edit.quoteLength( QLatin1String( "|Hello" ) ), 1 ); QCOMPARE( edit.quoteLength( QLatin1String( "| |Hello" ) ), 3 ); } void TextEditTester::testCleanText() { TextEdit edit; QLatin1String html( "Heelllo World
Bye!" ); QLatin1String plain( "Heelllo World\nBye!" ); edit.setTextOrHtml( html ); edit.addImage( KIconLoader::global()->iconPath( QLatin1String( "folder-new" ), KIconLoader::Small, false ) ); QVERIFY( edit.textMode() == TextEdit::Rich ); QCOMPARE( edit.toCleanPlainText(), plain ); edit.show(); // < otherwise toWrappedPlainText can't work, it needs a layout QCOMPARE( edit.toWrappedPlainText(), plain ); } void TextEditTester::testEnter_data() { QTest::addColumn("initalText"); QTest::addColumn("expectedText"); QTest::addColumn("cursorPos"); QTest::newRow( "" ) << QString::fromAscii( "> Hello World" ) << QString::fromAscii( "> Hello \n> World" ) << 8; QTest::newRow( "" ) << QString::fromAscii( "Hello World" ) << QString::fromAscii( "Hello \nWorld" ) << 6; QTest::newRow( "" ) << QString::fromAscii( "> Hello World" ) << QString::fromAscii( "> Hello World\n" ) << 13; QTest::newRow( "" ) << QString::fromAscii( ">Hello World" ) << QString::fromAscii( ">Hello \n>World" ) << 7; QTest::newRow( "" ) << QString::fromAscii( "> > Hello World" ) << QString::fromAscii( "> > Hello \n> > World" ) << 10; QTest::newRow( "" ) << QString::fromAscii( "| | Hello World" ) << QString::fromAscii( "| | Hello \n| | World" ) << 10; } void TextEditTester::testEnter() { QFETCH( QString, initalText ); QFETCH( QString, expectedText ); QFETCH( int, cursorPos ); TextEdit edit; edit.setPlainText( initalText ); QTextCursor textCursor( edit.document() ); textCursor.setPosition( cursorPos ); edit.setTextCursor( textCursor ); QTest::keyClick( &edit, Qt::Key_Return ); QCOMPARE( edit.toPlainText(), expectedText ); } void TextEditTester::testImages() { TextEdit edit; QString image1Path = KIconLoader::global()->iconPath( QLatin1String( "folder-new" ), KIconLoader::Small, false ); QString image2Path = KIconLoader::global()->iconPath( QLatin1String( "arrow-up" ), KIconLoader::Small, false ); // Add one image, check that embeddedImages() returns the right stuff edit.addImage( image1Path ); KPIMTextEdit::ImageList images = edit.embeddedImages(); + KPIMTextEdit::ImageWithNameList imagesWithNames = edit.imagesWithName(); QCOMPARE( images.size(), 1 ); + QCOMPARE( imagesWithNames.size(), 1 ); EmbeddedImage *image = images.first().data(); + ImageWithName *imageWithName = imagesWithNames.first().data(); QCOMPARE( image->imageName, QString::fromAscii( "folder-new.png" ) ); + QCOMPARE( imageWithName->name, QString::fromAscii( "folder-new.png" ) ); // Also check that it loads the correct image QImage diskImage( image1Path ); QBuffer buffer; buffer.open( QIODevice::WriteOnly ); diskImage.save( &buffer, "PNG" ); + QBuffer imageWithNameBuffer; + imageWithNameBuffer.open( QIODevice::WriteOnly ); + imageWithName->image.save( &imageWithNameBuffer, "PNG" ); QByteArray encodedImage = KMime::Codec::codecForName( "base64" )->encode( buffer.buffer() ); QCOMPARE( image->image, encodedImage ); + QCOMPARE( buffer.buffer(), imageWithNameBuffer.buffer() ); // No image should be there after clearing edit.clear(); QVERIFY( edit.embeddedImages().isEmpty() ); + QVERIFY( edit.imagesWithName().isEmpty() ); // Check that manually removing the image also empties the image list edit.addImage( image1Path ); QCOMPARE( edit.embeddedImages().size(), 1 ); + QCOMPARE( edit.imagesWithName().size(), 1 ); QTextCursor cursor = edit.textCursor(); cursor.setPosition( 0, QTextCursor::MoveAnchor ); cursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, 1 ); cursor.removeSelectedText(); QVERIFY( edit.embeddedImages().isEmpty() ); + QVERIFY( edit.imagesWithName().isEmpty() ); // Check that adding the identical image two times only adds the image once edit.addImage( image1Path ); edit.addImage( image1Path ); QCOMPARE( edit.embeddedImages().size(), 1 ); + QCOMPARE( edit.imagesWithName().size(), 1 ); // Another different image added, and we should have two images edit.clear(); edit.addImage( image1Path ); edit.addImage( image2Path ); images = edit.embeddedImages(); + imagesWithNames = edit.imagesWithName(); QCOMPARE( images.size(), 2 ); + QCOMPARE( imagesWithNames.size(), 2 ); KPIMTextEdit::EmbeddedImage *image1 = images.first().data(); KPIMTextEdit::EmbeddedImage *image2 = images.last().data(); + KPIMTextEdit::ImageWithName *imageWithName1 = imagesWithNames.first().data(); + KPIMTextEdit::ImageWithName *imageWithName2 = imagesWithNames.last().data(); QCOMPARE( image1->imageName, QString::fromAscii( "folder-new2.png" ) ); // ### FIXME: should be folder-new.png, but QTextEdit provides no way to remove cached resources! + QCOMPARE( imageWithName1->name, QString::fromAscii( "folder-new2.png" ) ); QCOMPARE( image2->imageName, QString::fromAscii( "arrow-up.png" ) ); + QCOMPARE( imageWithName2->name, QString::fromAscii( "arrow-up.png" ) ); QVERIFY( image1->contentID != image2->contentID ); } void TextEditTester::testImageHtmlCode() { TextEdit edit; QString image1Path = KIconLoader::global()->iconPath( QLatin1String( "folder-new" ), KIconLoader::Small, false ); QString image2Path = KIconLoader::global()->iconPath( QLatin1String( "arrow-up" ), KIconLoader::Small, false ); edit.addImage( image1Path ); edit.addImage( image2Path ); KPIMTextEdit::ImageList images = edit.embeddedImages(); QCOMPARE( images.size(), 2 ); KPIMTextEdit::EmbeddedImage *image1 = images.first().data(); KPIMTextEdit::EmbeddedImage *image2 = images.last().data(); QString startHtml = QLatin1String( "BlaBlub" ); QString endHtml = QString( QLatin1String( "BlaBlub" ) ) .arg( image2->contentID ).arg( image1->contentID ); QCOMPARE( TextEdit::imageNamesToContentIds( startHtml.toAscii(), images ), endHtml.toAscii() ); } void TextEditTester::testDeleteLine_data() { QTest::addColumn("initalText"); QTest::addColumn("expectedText"); QTest::addColumn("cursorPos"); QTest::newRow( "" ) << QString::fromAscii( "line1\nline2\nline3" ) << QString::fromAscii( "line1\nline3" ) << 6; QTest::newRow( "" ) << QString::fromAscii( "line1\nline2\nline3" ) << QString::fromAscii( "line2\nline3" ) << 5; QTest::newRow( "" ) << QString::fromAscii( "line1\nline2\nline3" ) << QString::fromAscii( "line1\nline3" ) << 11; QTest::newRow( "" ) << QString::fromAscii( "line1\nline2\nline3" ) << QString::fromAscii( "line2\nline3" ) << 0; QTest::newRow( "" ) << QString::fromAscii( "line1\nline2\nline3" ) << QString::fromAscii( "line1\nline2" ) << 17; QTest::newRow( "" ) << QString::fromAscii( "line1" ) << QString::fromAscii( "" ) << 0; QTest::newRow( "" ) << QString::fromAscii( "line1" ) << QString::fromAscii( "" ) << 5; // Now, test deletion with word wrapping. The line with the Ms is so long that it will get wrapped QTest::newRow( "" ) << QString::fromAscii( "line1\nMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3" ) << QString::fromAscii( "line1\nMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3" ) << 6; QTest::newRow( "" ) << QString::fromAscii( "line1\nMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3" ) << QString::fromAscii( "line1\nMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3" ) << 13; } void TextEditTester::testDeleteLine() { QFETCH( QString, initalText ); QFETCH( QString, expectedText ); QFETCH( int, cursorPos ); TextEdit edit; edit.setPlainText( initalText ); QTextCursor cursor = edit.textCursor(); cursor.setPosition( cursorPos ); edit.setTextCursor( cursor ); edit.show(); // we need a layout for this to work edit.deleteCurrentLine(); QCOMPARE( edit.toPlainText(), expectedText ); } +void TextEditTester::testLoadImage() +{ + TextEdit edit; + QString image1Path = KIconLoader::global()->iconPath( QLatin1String( "folder-new" ), KIconLoader::Small, false ); + QString image2Path = KIconLoader::global()->iconPath( QLatin1String( "arrow-up" ), KIconLoader::Small, false ); + QImage image1, image2; + QVERIFY( image1.load( image1Path ) ); + QVERIFY( image2.load( image1Path ) ); + + edit.setHtml( QLatin1String( "BlaBla" ) ); + + // First try to load an image with a name that doesn't match, it should fail + edit.loadImage( image1, QString::fromLatin1( "doesntmatch" ), QString::fromLatin1( "folder-new" ) ); + QVERIFY( !edit.document()->resource( QTextDocument::ImageResource, QUrl( QLatin1String( "folder-new" ) ) ).isValid() ); + + // Now, load the image for real + edit.loadImage( image1, QString::fromLatin1( "folder-new.png" ), QString::fromLatin1( "folder-new" ) ); + QVERIFY( edit.document()->resource( QTextDocument::ImageResource, QUrl( QLatin1String( "folder-new" ) ) ).isValid() ); + + // New test with a new textedit (so that we don't use the cached resources + // This example has two images in the same text block, make sure that doesn't crash (bug 204214) + TextEdit edit2; + edit2.setHtml( QLatin1String( "" ) ); + edit2.loadImage( image1, QString::fromLatin1( "folder-new.png" ), QString::fromLatin1( "folder-new" ) ); + QVERIFY( edit.document()->resource( QTextDocument::ImageResource, QUrl( QLatin1String( "folder-new" ) ) ).isValid() ); + QCOMPARE( edit.embeddedImages().size(), 1 ); +} + + diff --git a/kpimtextedit/tests/textedittest.h b/kpimtextedit/tests/textedittest.h index dc7a86b90..c961f9b6a 100644 --- a/kpimtextedit/tests/textedittest.h +++ b/kpimtextedit/tests/textedittest.h @@ -1,41 +1,42 @@ /* Copyright (c) 2009 Thomas McGuire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TEXTEDITTEST_H #define TEXTEDITTEST_H #include class TextEditTester : public QObject { Q_OBJECT private slots: void testFormattingUsed(); void testQuoting(); void testCleanText(); void testEnter(); void testEnter_data(); void testImages(); void testImageHtmlCode(); void testDeleteLine(); void testDeleteLine_data(); + void testLoadImage(); }; #endif